package com.secsbrain.cmdb.biz.impl;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import com.alibaba.fastjson.JSON;
import com.secsbrain.cmdb.biz.IHostService;
import com.secsbrain.cmdb.biz.utils.AESUtil;
import com.secsbrain.cmdb.biz.utils.HostUtils;
import com.secsbrain.cmdb.client.model.App;
import com.secsbrain.cmdb.dal.mapper.HostMapper;
import com.secsbrain.cmdb.dal.model.AppSystem;
import com.secsbrain.cmdb.dal.model.Host;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import com.secsbrain.common.concurrent.ExecutorManager;
import com.baomidou.framework.service.impl.SuperServiceImpl;
import com.baomidou.mybatisplus.plugins.Page;

/**
 *
 * Host 表数据服务层接口实现类
 *
 */
@Service
public class HostServiceImpl extends SuperServiceImpl<HostMapper, Host> implements IHostService {

	private static final Logger logger = LoggerFactory.getLogger(HostServiceImpl.class);

	@Value("${cmdb.saltstack.agent.url:}")
	private String saltstackAgentUrl;
	
	@Value("${passport.key:123456}")
	private String passportKey;
	
	/* (non-Javadoc)
	 * @see IHostService#queryHostPageList(com.baomidou.mybatisplus.plugins.Page, Host)
	 */
	@Override
	public Page<Host> queryHostPageList(Page<Host> pageBean, Host params) {
		pageBean.setRecords(this.baseMapper.queryHostPageList(pageBean, params));
		return pageBean;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see IHostService#initServer()
	 */
	@Override
	public void loadServer(String userName) throws IOException {
		logger.debug("加载服务器信息，配置的代理地址为："+saltstackAgentUrl);
		if(saltstackAgentUrl.indexOf(",")!=-1){
			String[] agentUrlArray=saltstackAgentUrl.split(",");
			for(String agentUrl:agentUrlArray){
				ExecutorManager.getInstance().execute(new Runnable() {
					
					@Override
					public void run() {
						loadByAgent(userName, agentUrl);
					}
				});
			}
		}else{
			loadByAgent(userName,saltstackAgentUrl);
		}
	}
	
	@SuppressWarnings({ "rawtypes", "unchecked" })
	@Transactional
	public void loadByAgent(String userName,String agentUrl){
		logger.debug("开始请求获取host信息。。。，agentUrl：{}",agentUrl);

		Date now = new Date();

		Map result = null;
		try {
			String hostRes = new RestTemplate().getForObject(agentUrl + "/salt/getHost", String.class);
			result = JSON.parseObject(AESUtil.decrypt(hostRes, passportKey), Map.class);
		} catch (Exception e) {
			throw new RuntimeException(e);
		}

		if (!(Boolean) result.get("success")) {
			throw new RuntimeException((String) result.get("errorMsg"));
		}

		List<Host> newServerList = new ArrayList<>();
		Set set = result.keySet();

		List<String> list = (List<String>) set.stream().map(String::valueOf)
				.collect(Collectors.toCollection(ArrayList::new));
		deleteUnknownServer(list);

		for (Object serverHostName : result.keySet()) {
			logger.debug("serverHostName:{}", serverHostName);
			logger.debug("result:{}", result.get(serverHostName));

			Host serverItem = new Host();
			serverItem.setHostName(String.valueOf(serverHostName));
			serverItem.setDelStatus(0);
			Host server = this.selectOne(serverItem);
			if (server != null) {
				serverItem = server;
			}
			Object resultObj = result.get(serverHostName);
			if (resultObj instanceof Map && serverItem.getId() == null) {
				Map infoMap = (Map) resultObj;
				parsePropertyFromMap(serverItem, infoMap);
				serverItem.setCreator("系统同步");
				serverItem.setCreateTime(now);
				serverItem.setEnv("none");
				serverItem.setIstatus(1);//新增的机器默认在用
				/* new */
				newServerList.add(serverItem);
			} else if (resultObj instanceof Map) {
				Map infoMap = (Map) resultObj;
				parsePropertyFromMap(serverItem, infoMap);
				serverItem.setUpdateTime(now);
//				serverItem.setUpdator(userName);
				/* update */
				this.updateSelectiveById(serverItem);
			} else if (serverItem.getId() != null) {
				/* down */
				// serverItem.setRunState(ServerRunState.DOWN);
				// serverItem.setUpdatedTime(now);
				this.updateSelectiveById(serverItem);
			}
		}
		if (!newServerList.isEmpty()) {
			newServerList.forEach(s -> this.insertSelective(s));
		}
	}

	private void deleteUnknownServer(List<String> list) {
		// List<Long> serverIds = serverMapper.selectUnknownServer(list);
		// if (serverIds.isEmpty()) {
		// return;
		// }
		// serverMapper.changeServersRunState(serverIds, ServerRunState.DELETE);
	}

	@SuppressWarnings("rawtypes")
	private void parsePropertyFromMap(Host server, Map infoMap) {
		Object ipList = infoMap.get("ipv4");
		if (ipList instanceof List) {
			List list = ((List) ipList);
			list.remove("127.0.0.1");
			server.setIp(list.toString());
		}
		server.setCpuarch(String.valueOf(infoMap.get("cpuarch")));
		server.setCpuModel(String.valueOf(infoMap.get("cpu_model")));
		server.setOs(String.valueOf(infoMap.get("os")));
		server.setHost(String.valueOf(infoMap.get("fqdn")));
		server.setKernel(String.valueOf(infoMap.get("kernel")));
		server.setKernelRelease(String.valueOf(infoMap.get("kernelrelease")));
		server.setMemTotal(Integer.parseInt(String.valueOf(infoMap.get("mem_total"))));
		server.setNumCpus(Integer.parseInt(String.valueOf(infoMap.get("num_cpus"))));
		server.setOsrelease(String.valueOf(infoMap.get("osrelease")));
		server.setOsarch(infoMap.get("osarch") == null ? null : String.valueOf(infoMap.get("osarch")));
		server.setProductname(infoMap.get("productname") == null ? null : String.valueOf(infoMap.get("productname")));
		server.setSaltversion(String.valueOf(infoMap.get("saltversion")));
		server.setSystemSerialnumber(
				infoMap.get("serialnumber") == null ? null : String.valueOf(infoMap.get("serialnumber")));
		server.setType(String.valueOf(infoMap.get("virtual")));
		server.setMinionStatus(1);// TODO
	}

	/* (non-Javadoc)
	 * @see IHostService#hostUseApp(java.lang.Long)
	 */
	@Override
	public List<App> hostUseApp(Long hostId) {
		List<AppSystem> appSystemList=this.baseMapper.hostLikeUseApp(hostId);
		List<App> appList=new ArrayList<App>();
		if(hostId==null){
			return appList;
		}
		for(AppSystem appSystem:appSystemList){
			App app=new App();
			app.setId(appSystem.getId());
			app.setName(appSystem.getName());
			
			String hostIds=appSystem.getHostIds();
//			if(StringUtils.isEmpty(hostIds)){
//				continue;
//			}
			if(hostIds.indexOf(",")!=-1){
				boolean flag=false;
				for(String hostIdStr:hostIds.split(",")){
					if(hostId.equals(Long.parseLong(hostIdStr))){
						flag=true;
						break;
					}
				}
				if(flag){
					appList.add(app);
				}
			}else{
				if(hostId.equals(Long.parseLong(hostIds))){
					appList.add(app);
				}
				
			}
			
		}
		return appList;
	}

	/* (non-Javadoc)
	 * @see IHostService#queryIpByHost(java.lang.String[])
	 */
	@Override
	public Map<String, List<String>> queryIpByHost(String[] hostList) {
		Host params=new Host();
		params.setHostNames(hostList);
		List<Host> list=this.baseMapper.queryHostByHostNames(params);
		Map<String, List<String>> map=new HashMap<String, List<String>>();
		for(Host host:list){
			map.put(host.getHostName(), HostUtils.getIpList(host.getIp()));
		}
		return map;
	}

}